package cn.edu.mju.dilidili.common.utils;

import lombok.Data;

// 规范全局代码, 不做自定义
// 考虑到可能会出现具体内容不固定的消息, 但是同一个状态码消息格式必须固定
// 为了良好的阅读性, 使用泛型作为数据类型而不是Object
@Data
public class Result<T> {
    private Integer code;
    private String msg;
    private T data;

    /**
     * 先状态码后数据表示如果数据为null该返回什么
     * 即如果数据非null返回 0 状态码, 否则就是传入的状态码
     */
    public Result(StateCode stateCode, T data) {
        this(data, stateCode);
        if (data != null) {
            stateCode = StateCode.SUCCESS;
        }
        this.msg = stateCode.msg;
        this.code = stateCode.code;
    }

    /**
     * 只有数据可以认为是正确的
     */
    public Result(T data) {
        this(data, StateCode.SUCCESS);
    }

    /**
     * 都没给那就不知道是什么引发的错误
     */
    public Result() {
        this(null, StateCode.OTHER_ERROR);
    }

    /**
     * 只给了状态码表示要返回这个状态
     */
    public Result(StateCode stateCode) {
        this(null, stateCode);
    }

    /**
     * 先数据再状态表示同时指定状态码和数据的内容
     */
    public Result(T data, StateCode stateCode) {
        this.data = data;
        this.msg = stateCode.msg;
        this.code = stateCode.code;
    }

    /**
     * 数据, 状态码, format参数内容, 因为部分状态码的内容并不一定是固定的
     */
    public Result(T data, StateCode stateCode, Object... args) {
        this.data = data;
        this.msg = String.format(stateCode.msg, args);
        this.code = stateCode.code;
    }

    public Result(StateCode stateCode, Object... args) {
        this(null, stateCode, args);
    }

    // 同时指定的封装
    public static <T> Result<T> ok(T data) {
        return new Result<>(data);
    }

    // 同时指定的封装2
    public static <T> Result<T> success(T data) {
        return new Result<>(data);
    }

    // 出现错误 其他错误 或者是叫默认错误
    public static <T> Result<T> error() {
        return new Result<>();
    }

    // 出现错误, 只给了状态码
    public static <T> Result<T> error(StateCode stateCode) {
        return new Result<>(stateCode);
    }

    // 出现错误, 给了状态码和数据, 还是调用了双指定的实现来完成
    public static <T> Result<T> error(StateCode stateCode, T data) {
        return new Result<>(data, stateCode);
    }

    // 最高程度自定义返回内容的方法, 可以格式化返回消息达到自定义的效果
    public static <T> Result<T> custom(T data, StateCode stateCode, Object... args) {
        return new Result<>(data, stateCode, args);
    }

    // 当传入的data 为null 时返回的状态码, 如果 非null 时, 就会返回成功状态码和数据, 失败时返回传入的状态码以及数据
    public static <T> Result<T> notNullData(T data, StateCode stateCode) {
        return new Result<>(stateCode, data);
    }

}

